|-app
    |-common 公共方法
        |-display.go 統一json格式輸出
    |-config 配置文件和统一路由管理
        |-message.yml 狀態碼文件
        |-route.go 路由配置文件
    |-controller 控制器
    |-dao database crud
    |-middleware 中間件
    |-model 模型
    |-service 核心業務
|-main.go 程序執行入口
大致上Gin Backend Service的 Item hierarchic會長這樣,但目前應該有許許多多的file是讀者完全不懂的,沒關係我們後面會依序地慢慢補上,這章節主要還是會環繞著route.go與main.go與service.go來解說
這邊主要是放api收到request後續所要執行的服務行為與response等
package app
import (
	"github.com/gin-gonic/gin"
	"net/http"
)
type UsersController struct {}
func NewUsersController() UsersController {
	return UsersController{}
}
func QueryUsersController() UsersController {
	return UsersController{}
}
func (u UsersController) CreateUser (c *gin.Context){
	c.JSON(http.StatusOK, gin.H{
		"status": 0,
		"msg":    "success Register",
		"data":   nil,
	})
}
func (u UsersController) GetUser (c *gin.Context){
	c.JSON(http.StatusOK, gin.H{
		"status": 0,
		"msg":    "success get data",
		"data":   nil,
	})
}
這邊則是放URL的規則與匹配路徑,以及該動作後續的執行行為等
package config
import (
	"github.com/gin-gonic/gin"
	"ironman-2021/app"
)
func RouteUsers(r *gin.Engine) {
	posts := r.Group("/v1/users")
	{
		posts.POST("/", app.NewUsersController().CreateUser)
		posts.GET("/", app.QueryUsersController().GetUser)
	}
}
最後則是main.go,我們創造一個gin.Default(),並除了health check api以外,我們也將其串連上了前面的RouteUsers()
package main
import (
	"github.com/gin-gonic/gin"
	"ironman-2021/app/config"
)
func main() {
	app := gin.Default()
	app.GET("/hc", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "health check",
		})
	})
	config.RouteUsers(app)
	err := app.Run(":8080")
	if err != nil {
		panic(err)
	}
}
最後的程式碼結構則會長這樣
.
|____go.mod
|____app
| |____service.go
| |____config
| | |____route.go
|____go.sum
|____main
|____main.go
|____.idea
| |____iron-man-2021.iml
| |____.gitignore
| |____workspace.xml
| |____modules.xml
最後則是來講解下,前面一直使用到的parameter gin.Context
// Context is the most important part of gin. It allows us to pass variables between middleware,
// manage the flow, validate the JSON of a request and render a JSON response for example.
type Context struct {
	writermem responseWriter
	Request   *http.Request
	Writer    ResponseWriter
	Params   Params
	handlers HandlersChain
	index    int8
	fullPath string
	engine *Engine
	params *Params
	// This mutex protect Keys map
	mu sync.RWMutex
	// Keys is a key/value pair exclusively for the context of each request.
	Keys map[string]interface{}
	// Errors is a list of errors attached to all the handlers/middlewares who used this context.
	Errors errorMsgs
	// Accepted defines a list of manually accepted formats for content negotiation.
	Accepted []string
	// queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query()
	queryCache url.Values
	// formCache use url.ParseQuery cached PostForm contains the parsed form data from POST, PATCH,
	// or PUT body parameters.
	formCache url.Values
	// SameSite allows a server to define a cookie attribute making it impossible for
	// the browser to send this cookie along with cross-site requests.
	sameSite http.SameSite
}
官方package當中已經有annotation明確指出,每個不同變數的用途已經定義,那這邊就不一一贅述。
簡單來說gin.Context就是把Request和Response做一個結構性的管理,但這也是建立在gin已經對於HTTP Request以以及Response進行了一定程度的封裝,才能做到如此的簡潔以及乾淨。
這章節主要是介紹Gin的程式碼放置與分類方式,以及Router的基本應用等,詳細程式碼則會放在以下連結。
https://github.com/Neskem/Ironman-2021/tree/Day-16